package kn.tool.file;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.core.io.ClassPathResource;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;

/**
 * @author: dengkunnan
 * @date: 2020-07-12 18:04
 * @description:
 **/
@Slf4j
public class FileDownloadUtil {
    /**
     * 文件下载，支持类路径下面的文件下载。
     *
     * @param fileName 文件名称，例如：profile.png
     * @param filePath 文件路径，例如resource/image文件夹下面的profile.png文件，filePath = "image/profile.png"
     * @param response 响应对象
     * @throws Exception
     * @throws IOException
     */
    public static void downloadFileByClassPathResource(String fileName, String filePath, HttpServletResponse response)
            throws Exception, IOException {
        if (StringUtils.isEmpty(fileName)) {
            log.error(">> 下载文件失败，文件名为空！");
            throw new Exception("文件名为空！");
        }

        if (StringUtils.isEmpty(filePath)) {
            log.error(">> 下载文件失败，文件路径为空！");
            throw new Exception("文件路径为空！");
        }

        ClassPathResource resource = new ClassPathResource(filePath);
        // 模板文件不存在
        if (!resource.exists()) {
            log.error(">> 下载失败，{}文件不存在！", filePath);
            throw new Exception("下载失败，文件不存在！");
        }
        response.setContentType("application/octet-stream");
        // 下载文件能正常显示中文
        response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));

        byte[] buffer = new byte[1024];
        BufferedInputStream bis = null;
        try {
            bis = new BufferedInputStream(resource.getInputStream());
            OutputStream outputStream = response.getOutputStream();
            int i = bis.read(buffer);
            while (i != -1) {
                outputStream.write(buffer, 0, i);
                i = bis.read(buffer);
            }
        } catch (Exception e) {
            log.error(">> 文件下载失败，errMsg:{}", e.getMessage());
            e.printStackTrace();
        } finally {
            if (bis != null) {
                try {
                    bis.close();
                } catch (IOException e) {
                    log.error(">> 文件下载失败，errMsg:{}", e.getMessage());
                    e.printStackTrace();
                }
            }
        }

        log.info(">> 文件下载成功！fileName:{}", fileName);
    }

    /**
     * 文件下载，支持File对象
     *
     * @param fileName 文件名称，例如：profile.png
     * @param file     文件对象
     * @param response 响应对象
     * @throws Exception
     * @throws IOException
     */
    public static void downloadFile(String fileName, File file, HttpServletResponse response)
            throws Exception, IOException {
        if (StringUtils.isEmpty(fileName)) {
            log.error(">> 下载文件失败，文件名为空！");
            throw new Exception("文件名为空！");
        }
        response.setContentType("application/octet-stream");
        // 下载文件能正常显示中文
        response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));

        byte[] buffer = new byte[1024];
        BufferedInputStream bis = null;
        InputStream is = null;
        OutputStream outputStream = null;
        try {
            is = new FileInputStream(file);
            bis = new BufferedInputStream(is);
            outputStream = response.getOutputStream();
            int i = bis.read(buffer);
            while (i != -1) {
                outputStream.write(buffer, 0, i);
                i = bis.read(buffer);
            }
        } catch (Exception e) {
            log.error(">> 文件下载失败，errMsg:{}", e.getMessage());
            e.printStackTrace();
        } finally {
            if (bis != null) {
                try {
                    if (outputStream != null) {
                        outputStream.close();
                    }
                    is.close();
                    bis.close();

                    // 删除临时文件
                    if (!file.delete()) {
                        log.info(">> 临时下载文件[{}]删除失败！", file.getAbsolutePath());
                    }
                } catch (IOException e) {
                    log.error(">> 文件下载失败，errMsg:{}", e.getMessage());
                    e.printStackTrace();
                }
            }
        }

        log.info(">> 文件下载成功！fileName:{}", fileName);
    }
}
